/*
 *	OpenSource code and fragments by avocado systems, Marcus Fuhrmeister
 *
 *	Redistribution and use in source and binary forms, with or without
 *	modification, are permitted provided that the following conditions
 *	are met:
 *  
 *		* Redistribution of source code must retain the above OpenSource comment,
 *		this list of conditions and the following disclaimer.
 * 
 *		* Redistribution in binary form must reproduce the above OpenSource comment,
 *		this list of conditions and the following disclaimer in the
 *		documentation and/or other materials provided with the distribution.
 * 
 *	Neither the name of 'avocaod systems, Marcus Fuhrmeister' or the
 *	names of contributors may be used to endorse or promote products derived
 *	from this software without specific prior written permission.
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 */
package de.fuhrmeister.browserchooser.controller;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.net.URL;
import java.util.Iterator;

import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;

import de.fuhrmeister.browserchooser.model.BrowserModel;
import de.fuhrmeister.browserchooser.model.BrowserVersionModel;
import de.fuhrmeister.browserchooser.view.BrowserVersionEntry;
import de.fuhrmeister.util.ConfigManager;
import de.fuhrmeister.util.Tools;

/**
 * Controller class handling the views.
 * 
 * @date 27.10.2009
 * @author Marcus Fuhrmeister
 */
public class BrowserShortcutViewPopupMenuController implements MouseListener {

	private static BrowserShortcutViewPopupMenuController self;

	/**
	 * Singleton pattern.
	 * 
	 * @return this
	 */
	public static synchronized BrowserShortcutViewPopupMenuController getInstance() {
		if (self == null) {
			BrowserShortcutViewPopupMenuController.self = new BrowserShortcutViewPopupMenuController();
			return BrowserShortcutViewPopupMenuController.self;
		}
		return BrowserShortcutViewPopupMenuController.self;
	}

	private JPopupMenu popup;

	private JMenuItem miSettings;

	private JLabel miLabel;

	private int browserID;

	/**
	 * Inits the popup menu.
	 * 
	 * @param label
	 *            the name of the browser
	 */
	private void initPopup(final String label) {
		popup = new JPopupMenu();
		miLabel = new JLabel();
		miLabel.setText(label);
		popup.add(miLabel);
		popup.addSeparator();
	}

	/**
	 * A call to JPopupMenu.show(Component invoker, int x, int y) will fail to
	 * show the JPopupMenu if the invoker passed in is an instance of JWindow.
	 * This is a known bug (bug id : 6539458) in JAVA JDK 1.6. The bug is not
	 * existend in minor versions and it will be fixed in JDK 1.7. This method
	 * has a workaround to show the popup anyway. Therefore it tests if the
	 * underlying JDK is a 1.6 version, opens a new JFrame right before showing
	 * the popup and disposes the frame afterwards.
	 * 
	 * @param component
	 *            the component the popup belongs to
	 * @param x
	 *            the x coordinate the popup will appear
	 * @param y
	 *            the y coordinate the popup will appear
	 * @param label
	 *            the browser name
	 * 
	 * @see URL http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6539458
	 */
	public void show(java.awt.Component component, final int x, final int y, final String label, final BrowserModel bm) {

		// JAVA 1.6 bug workaround
//		boolean isJDK6 = System.getProperty("java.version").startsWith("1.6");
//		final JFrame frame = new JFrame();
//		if (isJDK6) {
//			frame.setUndecorated(true);
//			frame.setSize(10, 10);
//			frame.setLocation(-100, -100);
//			frame.setVisible(true);
//			frame.setVisible(false);
//		}

		this.browserID = bm.getID();
		this.initPopup(label);
		if (!bm.isEmpty()) {
			final Iterator<BrowserVersionModel> i = bm.iterator();
			while (i.hasNext()) {
				final BrowserVersionModel bvm = i.next();
				final String versionString = bvm.getVersion() == null || bvm.getVersion().equalsIgnoreCase("") ? Tools.configMng.getStringFor(ConfigManager.STRING_LABEL_NOBROWSERVERSIONSTRING) : bvm.getVersion();
				final BrowserVersionEntry miVersion = new BrowserVersionEntry(versionString, bvm.getExec());
				if (miVersion.getExec() == null || miVersion.getExec().equals("")) {
					miVersion.setEnabled(false);
					miVersion.setToolTipText(ConfigManager.getInstance().getStringFor(ConfigManager.STRING_TOOLTIP_MENUITEM_SHORTCUT));
				} else {
					miVersion.addMouseListener(this);
				}

				popup.add(miVersion);
			}
			popup.addSeparator();
		}
		this.setPopupSettings();
		updateLanguage();
		popup.show(component, x, y);

		// JAVA 1.6 bug workaround
//		if (isJDK6) {
//			frame.dispose();
//		}
	}

	/**
	 * Adds the settings menu entry to the popup menu.
	 */
	private void setPopupSettings() {
		miSettings = new JMenuItem();
		miSettings.addMouseListener(this);
		popup.add(miSettings);
	}

	/**
	 * Closes the popup menu.
	 */
	public void close() {
		if (popup != null) {
			popup.setVisible(false);
			popup = null;
		}
	}

	/**
	 * Calls to update the language.
	 */
	public void updateGUI() {
		this.updateLanguage();
	}

	/**
	 * Updates the settings menu entry.
	 */
	public void updateLanguage() {
		if (popup != null) {
			miSettings.setText(Tools.configMng.getStringFor(ConfigManager.STRING_LABEL_OPTIONS) + "...");
		}
	}

	public void mouseClicked(final MouseEvent e) {
	}

	public void mouseEntered(final MouseEvent e) {
	}

	public void mouseExited(final MouseEvent e) {
	}

	public void mousePressed(final MouseEvent e) {
	}

	/**
	 * Calls to open the browser version or calls to open the settings dialog.
	 * 
	 * @param e the mouse event
	 */
	public void mouseReleased(final MouseEvent e) {
		if (e.getSource() instanceof BrowserVersionEntry) {
			try {
				final BrowserVersionEntry bve = (BrowserVersionEntry) e.getSource();

				if (bve.getExec() != null && !bve.getExec().equals("") && Controller.isExecutable(bve.getExec())) {
					Tools.browserLauncher.execute(bve.getExec());
				} else {
					Tools.messageBox.inform(Controller.getInstance().getWindow(Controller.APP_WINDOW_MAIN), Tools.configMng.getStringFor(ConfigManager.MESSAGE_TITLE_INFORMATION), Tools.configMng.getStringFor(ConfigManager.MESSAGE_VALUE_ERROR_EXECUTABLENOTHANDABLE));
				}
			} catch (final NullPointerException npe) {
				Tools.messageBox.inform(Controller.getInstance().getWindow(Controller.APP_WINDOW_MAIN), Tools.configMng.getStringFor(ConfigManager.MESSAGE_TITLE_INFORMATION), Tools.configMng.getStringFor(ConfigManager.MESSAGE_VALUE_ERROR_NOEXECUTABLE));
			} catch (final IndexOutOfBoundsException ioobe) {
				Tools.messageBox.inform(Controller.getInstance().getWindow(Controller.APP_WINDOW_MAIN), Tools.configMng.getStringFor(ConfigManager.MESSAGE_TITLE_INFORMATION), Tools.configMng.getStringFor(ConfigManager.MESSAGE_VALUE_ERROR_NOEXECUTABLE));
			} catch (final IllegalArgumentException iae) {
				Tools.messageBox.inform(Controller.getInstance().getWindow(Controller.APP_WINDOW_MAIN), Tools.configMng.getStringFor(ConfigManager.MESSAGE_TITLE_INFORMATION), Tools.configMng.getStringFor(ConfigManager.MESSAGE_VALUE_ERROR_NOEXECUTABLE));
			}
		} else {
			SettingsController.getInstance().show(this.browserID);
		}
	}
}